#include "rtc.h"

#include <math.h>

volatile uint32_t g_rtc_wakeup_event=0;  // 用于rtc定时器确认可以获取日期时间

/**
 @brief 初始化RTC
*/
void rtc_init(void)
{
	RTC_InitTypeDef  RTC_InitStructure;
	EXTI_InitTypeDef  EXTI_InitStructure;
	NVIC_InitTypeDef  NVIC_InitStructure;
    	
    /* Enable the PWR clock，使能电源管理时钟 */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
    
    /* Allow access to RTC，允许访问备份电路，备份电路包含了RTC */
    PWR_BackupAccessCmd(ENABLE);
    
    /* Enable the LSE OSC，使能LSE的振荡时钟（32.768KHz） */
    RCC_LSEConfig(RCC_LSE_ON);
    
    /* Wait till LSE is ready，等待LSE就绪 */  
    while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
    
    /* Select the RTC Clock Source，选中LSE作为RTC的时钟源 */
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
    
    /* Enable the RTC Clock，使能RTC的硬件时钟 */
    RCC_RTCCLKCmd(ENABLE);
    
    /* Wait for RTC APB registers synchronisation，等待RTC相关寄存器就绪 */
    RTC_WaitForSynchro();
    
    /* Configure the RTC data register and RTC prescaler*/
   
    /* ck_spre(1Hz) = RTCCLK(LSE) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)
	                = 32768 /(127+1)/(255+1)
					= 1Hz
	*/
    RTC_InitStructure.RTC_AsynchPrediv = 127;
    RTC_InitStructure.RTC_SynchPrediv = 255;
    RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
    RTC_Init(&RTC_InitStructure);
   
	//关闭唤醒功能
	RTC_WakeUpCmd(DISABLE);
	
	//为唤醒功能选择RTC配置好的时钟源
	RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits);
	
	//设置唤醒计数值为自动重载，写入值默认是0
	RTC_SetWakeUpCounter(1-1);
	
	//清除RTC唤醒中断标志
	RTC_ClearITPendingBit(RTC_IT_WUT);
	
	//使能RTC唤醒中断
	RTC_ITConfig(RTC_IT_WUT, ENABLE);

	//使能唤醒功能
	RTC_WakeUpCmd(ENABLE);

	/* Configure EXTI Line22，配置外部中断控制线22 */
	EXTI_InitStructure.EXTI_Line = EXTI_Line22;			//当前使用外部中断控制线22
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;		//中断模式
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;		//上升沿触发中断 
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;			//使能外部中断控制线22
	EXTI_Init(&EXTI_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn;		//允许RTC唤醒中断触发
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;	//抢占优先级为0x3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;		//响应优先级为0x3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//使能
	NVIC_Init(&NVIC_InitStructure);   
}


/**
 @brief  设置日期
 @param  year:    按照10进制方式16进制格式输入年份
 @param  mouth:   按照10进制方式16进制格式输入月份
 @param  date:    按照10进制方式16进制格式输入日份
 @param  weekday: 按照10进制方式16进制格式输入星期
 @refer  设置2022年2月22日星期一 rtc_set_date(0x22, 0x2, 0x22, 0x1);
*/
void rtc_set_date(uint8_t year, uint8_t month, uint8_t date, uint8_t weekday){
	RTC_DateTypeDef  RTC_DateStructure;
    /* Set the date: 2022/11/6 星期日 */
    RTC_DateStructure.RTC_Year = year;
    RTC_DateStructure.RTC_Month = month;
    RTC_DateStructure.RTC_Date = date;
    RTC_DateStructure.RTC_WeekDay = weekday;
    RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure);
}


/**
 @brief 设置时间
 @param hours:   按照10进制方式16进制格式输入小时
 @param minutes: 按照10进制方式16进制格式输入分钟
 @param seconds: 按照10进制方式16进制格式输入秒
 @refer 设置16:30:00 rtc_set_time(0x16, 0x30, 0x00);
*/
void rtc_set_time(uint8_t hours, uint8_t minutes, uint8_t seconds){
	RTC_TimeTypeDef  RTC_TimeStructure;
    /* Set the time to 16h 40mn 00s AM */
    if(hours>12){
	    RTC_TimeStructure.RTC_H12 = RTC_H12_PM;
    }else{
	    RTC_TimeStructure.RTC_H12 = RTC_H12_AM;
    }
    RTC_TimeStructure.RTC_Hours   = hours;
    RTC_TimeStructure.RTC_Minutes = minutes;
    RTC_TimeStructure.RTC_Seconds = seconds; 
    RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure);   
}

/**
 @brief RTC定时器
*/
void RTC_WKUP_IRQHandler(void){
	if (RTC_GetITStatus(RTC_IT_WUT) == SET)
	{
		g_rtc_wakeup_event=1;	  // 表明已经可以获取数据
	  
		RTC_ClearITPendingBit(RTC_IT_WUT);
		EXTI_ClearITPendingBit(EXTI_Line22);
	}
}

/**
 @brief 十进制转十六进制,22->0x22
 @param num: 十进制数
 @retval num十六进制形式
*/
uint32_t int_to_hex(uint32_t num)
{
	uint32_t hex_num=0,tmp_num;
	uint8_t i=0;  // 用于保存当前位数
	while(num>0){
		tmp_num = num/10;
		hex_num += (num - tmp_num*10) * pow(16, i);
		num = tmp_num;
		i++;
	}
	return hex_num;
}
